﻿
/// <reference path="Component.js" />
/// <reference path="_namespace.js" />

/*****************************************************************************
Ajax library class definition. Kevin Robinson 2006.
Class: ajax.components.DragController
/*****************************************************************************/

ajax.lang.addNamespace("ajax.components");

// Menu Constructor
//-----------------------------------------------------------------------------
ajax.components.DragController = function(doc, obj, root, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper)
{
    ajax.components.DragController.superConstructor.call(this, doc);
    
    var self = this;
    
    this.setSourceElement(obj);    
    
    this.hmode      = bSwapHorzRef ? false : true;
    this.vmode      = bSwapVertRef ? false : true;
    
    this.root = root && root != null ? root : this.ele;
    
    if (this.hmode && isNaN(parseInt(this.root.style.left))) this.root.style.left       = "0px";
    if (this.vmode && isNaN(parseInt(this.root.style.top))) this.root.style.top         = "0px";
    if (!this.hmode && isNaN(parseInt(this.root.style.right))) this.root.style.right    = "0px";
    if (!this.vmode && isNaN(parseInt(this.root.style.bottom))) this.root.style.bottom  = "0px";
    
    this.minX = (typeof(minX) != "undefined") ? minX : null;
    this.minY = (typeof(minY) != "undefined") ? minY : null;
    this.maxX = (typeof(maxX) != "undefined") ? maxX : null;
    this.maxY = (typeof(maxY) != "undefined") ? maxY : null;
    
    this.xMapper = fXMapper ? fXMapper : null;
    this.yMapper = fYMapper ? fYMapper : null;
    
    // Create Events that clients can subscribe to
    this.onDragStartRouter  = this.getEvent(this.window, "onDragStart");
    this.onDragEndRouter    = this.getEvent(this.window, "onDragEnd");
    this.onDragRouter       = this.getEvent(this.window, "onDrag");
    
    this.onMouseMoveRouter  = ajax.lang.getEvent(self.window, self.doc, "onmousemove");
    this.onMouseUpRouter    = ajax.lang.getEvent(self.window, self.doc, "onmouseup");
    
    this.onDragDelegate     = function(e){ self.drag(e); };
    this.onEndDelegate      = function(e){ self.end(e); };
}

//-----------------------------------------------------------------------------
ajax.lang.extend("ajax.components.DragController", "ajax.components.Component"); // Inherit

//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.setSourceElement = function(ele)
{
    // remove previous
    if (this.ele)
    {
        this.ele.dragController.removeHandler();
        this.ele.dragController = null;
    }
    // Add the new
    this.ele = ele;
    ele.dragController = this;
    this.addHandler();
}
//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.addHandler = function()
{
    ajax.lang.getEvent(this.window, this.ele, "onmousedown").addListener(this.dragStart);
}

//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.removeHandler = function()
{
    ajax.lang.getEvent(this.window, this.ele, "onmousedown").removeListener(this.dragStart);
}

//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.dragStart = function(e)
{
    var self = this.dragController;
    var o = this;    
    
    var y = parseInt(self.vmode ? self.root.style.top  : self.root.style.bottom);
    var x = parseInt(self.hmode ? self.root.style.left : self.root.style.right);
    
    // fire the onDragStartEvent of our object
    var eventArgs = {e: e, x: x, y: y};
    self.onDragStart.call(self, eventArgs);
    
    self.lastMouseX    = e.clientX;
    self.lastMouseY    = e.clientY;
    
    if (self.hmode)
    {
        if (self.minX != null) self.minMouseX = e.clientX - x + self.minX;
        if (self.maxX != null) self.maxMouseX = self.minMouseX + self.maxX - self.minX;
    }
    else
    {
        if (self.minX != null) self.maxMouseX = - self.minX + e.clientX + x;
        if (self.maxX != null) self.minMouseX = - self.maxX + e.clientX + x;       
    }
    
    if (self.vmode)
    {
        if (self.minY != null) self.minMouseY = e.clientY - y + self.minY;
        if (self.maxY != null) self.maxMouseY = self.minMouseY + self.maxY - self.minY;
    }
    else
    {
        if (self.minY != null) self.maxMouseY = - self.minY + e.clientY + y;
        if (self.maxY != null) self.minMouseY = - self.maxY + e.ClientY + y;
    }
      
    // MAKE SURE that the document will notify us of mousemove & mouseup events
    self.onMouseMoveRouter.returnFalse = true;
    // Use the Delegate so that it fires in the context of this DragController 
    self.onMouseMoveRouter.addListener(self.onDragDelegate);

    self.onMouseUpRouter.returnFalse = true;
    self.onMouseUpRouter.addListener(self.onEndDelegate);    
      
}

//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.drag = function(e)
{
    var self = this;
    var o = self.ele;
    
    var ey = e.clientY;
    var ex = e.clientX;
    var y = parseInt(self.vmode ? self.root.style.top : self.root.style.bottom);
    var x = parseInt(self.hmode ? self.root.style.left : self.root.style.right);
    var nx, ny;
    
    if (self.minX != null) ex = self.hmode ? Math.max(ex, self.minMouseX) : Math.min(ex, self.maxMouseX);
    if (self.maxX != null) ex = self.hmode ? Math.min(ex, self.maxMouseX) : Math.max(ex, self.minMouseX);
    
    if (self.minY != null) ey = self.vmode ? Math.max(ey, self.minMouseY) : Math.min(ey, self.maxMouseY);
    if (self.maxY != null) ey = self.vmode ? Math.min(ey, self.maxMouseY) : Math.max(ey, self.minMouseY);
    
    nx = x + ((ex - self.lastMouseX) * (self.hmode ? 1 : -1));
    ny = y + ((ey - self.lastMouseY) * (self.vmode ? 1 : -1));
    
    if (self.xMapper) 
        nx = self.xMapper(y);
    else if (self.yMapper)
        ny = self.yMapper(x);
    
    self.root.style[self.hmode ? "left" : "right"] = nx + "px";
    self.root.style[self.vmode ? "top" : "bottom"] = ny + "px";
    self.lastMouseX = ex;
    self.lastMouseY = ey;
    
    // Fire the OnDrag event
    var eventArgs = {e:e, x: nx, y: ny};
    self.onDrag.call(self, eventArgs);
    
    return false;       
}

//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.end = function(e)
{
    var self = this;
    var o = self.ele;
    
    // Remove document event handlers
    self.onMouseMoveRouter.removeListener(self.onDragDelegate);
    self.onMouseMoveRouter.returnFalse = false;
    
    self.onMouseUpRouter.removeListener(self.onEndDelegate);
    self.onMouseUpRouter.returnFalse = false;
    
    
    // Fire the End Event
    var ex = parseInt(self.root.style[self.hmode ? "left" : "right"]);
    var ey = parseInt(self.root.style[self.vmode ? "top" : "bottom"]);
    
    var eventArgs = {e: e, x: ex, y: ey};
    self.onDragEnd.call(self, eventArgs);
}

//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.toString = function()
{
    return "ajax.components.DragController";
}

//-----------------------------------------------------------------------------
ajax.components.DragController.prototype.toClassName = function()
{
    return ajax.lang.getClassName("ajax.components.DragController");
}


//-----------------------------------------------------------------------------
ajax.components.DragController.cast = function(obj)
{///<returns type="ajax.components.DragController"/>
    return obj;
}